package org.mozhu.mboot.admin.system.auth.web.controller;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.mozhu.mboot.admin.system.auth.entity.GroupAuth;
import org.mozhu.mboot.admin.system.auth.service.GroupAuthService;
import org.mozhu.mboot.admin.system.group.entity.Group;
import org.mozhu.mboot.admin.system.group.service.GroupService;
import org.mozhu.mboot.admin.system.privilege.service.PermissionService;
import org.mozhu.mboot.admin.system.privilege.service.RoleService;
import org.mozhu.mboot.core.util.BeanUtils;
import org.mozhu.mboot.core.web.Constants;
import org.mozhu.mboot.core.web.bind.annotation.ControllerDefaults;
import org.mozhu.mboot.core.web.controller.BaseCRUDController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@RequestMapping("/system/auth/group")
@Controller
@ControllerDefaults(resourceIdentity = "system:auth")
public class GroupAuthController extends BaseCRUDController<GroupAuth, Long> {

    @Autowired
    RoleService roleService;
    @Autowired
    PermissionService permissionService;
    @Autowired
    GroupService groupService;

    protected GroupAuthService getBaseService() {
        return (GroupAuthService) baseService;
    }

    @Override
    protected void setCommonData(Model model) {
        super.setCommonData(model);
        model.addAttribute("roles", roleService.findAll());
    }

    @Override
    protected Map<String, Object> getExtraData(HttpServletRequest request, Page<GroupAuth> page) {
        Map<String, Object> extraDataMap = Maps.newHashMap();
        AuthHelper authHelper = new AuthHelper(roleService, permissionService);
        List<GroupAuth> authList = page.getContent();
        extraDataMap.put("roles", authHelper.getRoles(authList));
        extraDataMap.put("permissions", authHelper.getPermissions(authList));
        extraDataMap.put("groups", getGroups(authList));
        return extraDataMap;
    }

    @Override
    protected void setExtraData(GroupAuth auth, Model model) {
        model.addAttribute("group", groupService.findById(auth.getGroupId()));
    }

    private Object getGroups(List<GroupAuth> authList) {
        Set<Long> groupIds = authList.stream().map(a -> a.getGroupId()).collect(Collectors.toSet());
        return groupService.findAllById(groupIds).stream().collect(Collectors.toMap(Group::getId, c -> BeanUtils.transBean2Map(c, "id", "name")));
    }

    @Override
    @RequestMapping(value = "create/discarded", method = RequestMethod.POST)
    public String create(HttpServletRequest request, Model model, @Valid @ModelAttribute("m") GroupAuth m, BindingResult result, @RequestParam(value = Constants.BACK_URL, required = false) String backURL, RedirectAttributes redirectAttributes) {
        throw new RuntimeException("discard method");
    }

    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(HttpServletRequest request, Model model, @RequestParam(value = "groupIds", required = false) Long[] groupIds,
                         @Valid @ModelAttribute("m") GroupAuth m, BindingResult result, @RequestParam(value = Constants.BACK_URL, required = false) String backURL, RedirectAttributes redirectAttributes) {
        this.permissions.assertHasCreatePermission();
        if (hasError(m, result)) {
            return showCreateForm(request, model);
        }
        try {
            this.getBaseService().addGroupAuth(groupIds, m);
            redirectAttributes.addFlashAttribute(Constants.MESSAGE, CREATE_SUCCESS);
        } catch (RuntimeException e) {
            logger.error("create fail", e);
            redirectAttributes.addFlashAttribute(Constants.ERROR, CREATE_FAIL);
        }
        return redirect(backURL);
    }

    @RequestMapping(value = "{id}/update", method = RequestMethod.POST)
    @Override
    public String update(HttpServletRequest request, Model model, @Valid @ModelAttribute("m") GroupAuth m, BindingResult result, @RequestParam(value = Constants.BACK_URL, required = false) String backURL,
                         RedirectAttributes redirectAttributes) {
        // select role 取消全选不能更新的bug
        String roleIds = request.getParameter("roleIds");
        if (StringUtils.isBlank(roleIds)) {
            m.setRoleIds(Sets.newHashSet());
        }
        super.update(request, model, m, result, backURL, redirectAttributes);
        return redirect(backURL);
    }
}